﻿using System;
using System.Collections;

using Storm.TextEditor.Editor;

namespace Storm.TextEditor.Parser.Objects.Collections
{
    /// <summary>
    /// Represents a list of Pattern.
    /// </summary>
    public sealed class PatternList
        : IEnumerable
    {
        #region Fields

        private PatternCollection patterns = new PatternCollection();
        private PatternCollection complexPatterns = new PatternCollection();
        private TextStyle style = new TextStyle();

        private Hashtable simplePatterns = new Hashtable();
        private Hashtable simplePatterns1Char = new Hashtable();
        private Hashtable simplePatterns2Char = new Hashtable();

        private bool caseSensitive = false;
        private bool normalizeCase = false;
        private string name = "";

        private PatternListList parent = null;
        private Block parentBlock = null;

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the Patterns of the PatternList.
        /// </summary>
        public PatternCollection Patterns
        {
            get { return patterns; }
            set { patterns = value; }
        }

        /// <summary>
        /// Gets or sets the complex Patterns of the PatternList.
        /// </summary>
        public PatternCollection ComplexPatterns
        {
            get { return complexPatterns; }
            set { complexPatterns = value; }
        }

        /// <summary>
        /// Gets or sets the TextStyle of the PatternList.
        /// </summary>
        public TextStyle Style
        {
            get { return style; }
            set { style = value; }
        }

        /// <summary>
        /// Gets or sets the simple Patterns of the PatternList.
        /// </summary>
        public Hashtable SimplePatterns
        {
            get { return simplePatterns; }
            set { simplePatterns = value; }
        }

        /// <summary>
        /// Gets or sets the simple Patterns with 1 char of the PatternList.
        /// </summary>
        public Hashtable SimplePatterns1Char
        {
            get { return simplePatterns1Char; }
            set { simplePatterns1Char = value; }
        }

        /// <summary>
        /// Gets or sets the simple Patterns with 2 chars of the PatternList.
        /// </summary>
        public Hashtable SimplePatterns2Char
        {
            get { return simplePatterns2Char; }
            set { simplePatterns2Char = value; }
        }

        /// <summary>
        /// Gets or sets whether the PatternList is case sensitive.
        /// </summary>
        public bool CaseSensitive
        {
            get { return caseSensitive; }
            set { caseSensitive = value; }
        }

        /// <summary>
        /// Gets or sets whether the PatternList should normalize case.
        /// </summary>
        public bool NormalizeCase
        {
            get { return normalizeCase; }
            set { normalizeCase = value; }
        }

        /// <summary>
        /// Gets or sets the name of the PatternList.
        /// </summary>
        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        /// <summary>
        /// Gets or sets the parent PatternListList of the PatternList.
        /// </summary>
        public PatternListList Parent
        {
            get { return parent; }
            set { parent = value; }
        }

        /// <summary>
        /// Gets or sets the parent Block of the PatternList.
        /// </summary>
        public Block ParentBlock
        {
            get { return parentBlock; }
            set { parentBlock = value; }
        }

        #endregion

        #region Methods

        #region Public

        /// <summary>
        /// Returns the IEnumerator of the PatternList.
        /// </summary>
        /// <returns>The IEnumerator of the PatternList.</returns>
        public IEnumerator GetEnumerator()
        {
            return patterns.GetEnumerator();
        }

        /// <summary>
        /// Adds the given Pattern to the PatternList.
        /// </summary>
        /// <param name="pattern">Pattern to add.</param>
        /// <returns>The added Pattern.</returns>
        public Pattern Add(Pattern pattern)
        {
            if (parent != null && parent.Parent != null && parent.Parent.Parent != null)
            {
                pattern.Separators = parent.Parent.Parent.Separators;
                parent.Parent.Parent.ChangeVersion();
            }

            if (pattern.IsComplex == false && pattern.ContainsSeparator == false)
            {
                string newPatternString = "";
                if (pattern.StringPattern.Length >= 2)
                    newPatternString = pattern.StringPattern.Substring(0, 2);
                else
                    newPatternString = pattern.StringPattern.Substring(0, 1) + " ";

                newPatternString = newPatternString.ToLower();
                if (pattern.StringPattern.Length == 1)
                    simplePatterns1Char[pattern.StringPattern] = pattern;
                else
                {
                    if (simplePatterns2Char[newPatternString] == null)
                        simplePatterns2Char[newPatternString] = new PatternCollection();

                    PatternCollection ar = (PatternCollection)simplePatterns2Char[newPatternString];
                    ar.Add(pattern);
                }

                if (caseSensitive == true)
                    simplePatterns[pattern.LowerStringPattern] = pattern;
                else
                    simplePatterns[pattern.StringPattern] = pattern;
            }
            else
                complexPatterns.Add(pattern);

            patterns.Add(pattern);
            if (pattern.Parent == null)
                pattern.Parent = this;
            else
                throw (new Exception("Pattern already assigned to another PatternList"));

            return pattern;
        }

        /// <summary>
        /// Clears the PatternList,
        /// </summary>
        public void Clear()
        {
            patterns.Clear();
        }

        #endregion

        #endregion

        /// <summary>
        /// Initializes a new instance of PatternList.
        /// </summary>
        public PatternList()
        {
            simplePatterns = new Hashtable(StringComparer.OrdinalIgnoreCase);
        }
    }
}
